package nveces.jspwiki.plugins.svg;

import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.BROWSER_MSIE;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.DOT;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.ENCODING_UTF_8;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.INTERVAL;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.JPEG_EXT;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.PARAM_MODE;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.PARAM_SRC;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.PARAM_TARGET;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.SLASH;
import static nveces.jspwiki.plugins.svg.MagicNamesPluginSvg.USER_AGENT;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.GregorianCalendar;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.apache.batik.transcoder.TranscoderException;
import org.apache.log4j.Logger;

import com.ecyrd.jspwiki.WikiContext;
import com.ecyrd.jspwiki.attachment.Attachment;
import com.ecyrd.jspwiki.plugin.PluginException;
import com.ecyrd.jspwiki.plugin.WikiPlugin;
import com.ecyrd.jspwiki.providers.ProviderException;
import com.ecyrd.jspwiki.providers.WikiPageProvider;

/**
 * $Id: SvgPlugin.java 33 2011-03-17 23:29:14Z nveces@gmail.com $
 *
 * @author nveces
 *
 */
@SuppressWarnings("unchecked")
public class SvgPlugin implements WikiPlugin {

    private static final Logger log = Logger.getLogger(SvgPlugin.class);

    public SvgPlugin() {
    }

    @Override
    public String execute(WikiContext context, Map map) throws PluginException {
        //
        this.logMap(map);
        String src = (String) map.get(PARAM_SRC);
        String mode = (String) map.get(PARAM_MODE);
        if (mode == null || (this.is_ie(context) && !SvgMode.ATTACH.toString().equalsIgnoreCase(mode))) {
            mode = SvgMode.IMAGE.name();
        }
        StringBuffer result = new StringBuffer();
        try {
            Attachment att = context.getEngine().getAttachmentManager().getAttachmentInfo(src);
            switch (SvgMode.valueOf(mode.toUpperCase())) {
            case ATTACH:
                result.append(this.getAttachMode(context, att, map));
                break;
            case INLINE:
                result.append(this.getInlineMode(context, att, map));
                break;
            case OBJECT:
                result.append(this.getObjectMode(context, att, map));
                break;
            default:
                // case IMAGE:
                result.append(this.getImageMode(context, att, map));
                break;
            }
        } catch (ProviderException e) {
            //
            log.error("execute()--->ProviderException: " + e.getMessage(), e);
            throw new PluginException("execute()--->Problem in getAttachmentManager", e);
        } catch (IOException e) {
            //
            log.error("execute()--->IOException: " + e.getMessage(), e);
            throw new PluginException("execute()--->Problem in getAttachmentManager", e);
        } catch (TranscoderException e) {
            //
            log.error("execute()--->TranscoderException: " + e.getMessage(), e);
            throw new PluginException("execute()--->Problem in getAttachmentManager", e);
        }

        return result.toString();
    }

    private StringBuffer getAttachMode(WikiContext context, Attachment att, Map map) {
        String target = (String) map.get(PARAM_TARGET);
        String label = att.getName();
        String href = context.getURL(WikiContext.ATTACH, att.getName());
        return HtmlTagCreator._().createLink(target, href, label);
    }

    private StringBuffer getInlineMode(WikiContext context, Attachment att, Map map) throws ProviderException, IOException {
        StringBuffer sb = new StringBuffer();
        InputStream is = context.getEngine().getAttachmentManager().getAttachmentStream(att);
        InputStreamReader isr = new InputStreamReader(is, ENCODING_UTF_8);
        Reader in = new BufferedReader(isr);
        int ch;
        while ((ch = in.read()) > -1) {
            sb.append((char) ch);
        }
        in.close();
        return sb;
    }

    private StringBuffer getObjectMode(WikiContext context, Attachment att, Map map) {
        String href = context.getURL(WikiContext.ATTACH, att.getName());
        return HtmlTagCreator._().createObject(map, href);
    }

    private StringBuffer getImageMode(WikiContext context, Attachment att, Map map) throws ProviderException, IOException, TranscoderException {
        int pos = att.getFileName().lastIndexOf(DOT);
        String src = att.getFileName().substring(0, pos);
        String imgsrc = this.dtranscode(context, att, src, map);
        return HtmlTagCreator._().createImg(map, imgsrc);
    }

    private void setAttribute(WikiContext context, String key, Object value) {
        HttpSession session = null;
        session = context.getHttpRequest().getSession();
        session.setAttribute(key, value);
    }

    private String dtranscode(WikiContext context, Attachment att, String src, Map map) throws ProviderException, IOException, TranscoderException {
        StringBuffer imagename = new StringBuffer();
        imagename.append(att.getParentName());
        imagename.append(SLASH);
        imagename.append(src);
        imagename.append(JPEG_EXT);
        Svg2Image svg2image = new Svg2Image();
        Attachment attinfo = context.getEngine().getAttachmentManager().getAttachmentInfo(imagename.toString(), WikiPageProvider.LATEST_VERSION);
        long lastmodified = attinfo.getLastModified().getTime();
        long nowTime = GregorianCalendar.getInstance().getTimeInMillis();
        long diff = (nowTime - lastmodified);
        log.info("dtranscode()--->Diff: " + diff);
        boolean generateJPG = false;
        if (INTERVAL < diff) {
            // Out interval
            generateJPG = true;
        } else {
            // In Interval
            generateJPG = false;
        }
        log.info("dtranscode()--->GenerateJPG? " + generateJPG);
        String attName = imagename.toString();
        if (attinfo == null || generateJPG) {
            InputStream is = context.getEngine().getAttachmentManager().getAttachmentStream(att);
            byte[] out = svg2image.dtranscode(is);
            ByteArrayInputStream bais = new ByteArrayInputStream(out);
            Attachment attachment = new Attachment(context.getEngine(), context.getPage().getName(), src + JPEG_EXT);
            context.getEngine().getAttachmentManager().storeAttachment(attachment, bais);
            bais.close();
            attName = attachment.getName();
            return context.getURL(WikiContext.ATTACH, attachment.getName());
        }
        setAttribute(context, src, imagename);
        return context.getURL(WikiContext.ATTACH, attName);
    }

    private boolean is_ie(WikiContext context) {
        String useragent = context.getHttpRequest().getHeader(USER_AGENT).toLowerCase();
        if (log.isDebugEnabled()) {
            log.debug("is_ie()--->User-Agent: " + useragent);
        }
        if (useragent.indexOf(BROWSER_MSIE) != -1) {
            return true;
        } else {
            return false;
        }
    }

    private void logMap(Map map) {
        if (!log.isDebugEnabled()) {
            return;
        }
        for (Object obj : map.entrySet()) {
            log.debug("logMap()--->Entry: " + obj.getClass());
        }
    }

    /*
     * context.getEngine().getWorkDir()); String pagecontent =
     * context.getEngine(
     * ).getPageManager().getPageText(context.getPage().getName(),
     * WikiPageProvider.LATEST_VERSION);
     */

}
